﻿#include "qinifile.h"

#define  DEF_PROFILE_THRESHOLD 512

#ifndef FALSE
#define FALSE               0
#endif

#ifndef TRUE
#define TRUE                1
#endif

QIniFile::QIniFile()
{

}

QIniFile::QIniFile(const char* sPath) :m_sPath(sPath)
{
    QLibrary lib("kernel32");
    bool suc = lib.load();
    if (suc)
    {
        fnGetPrivateProfileSectionNamesA = (PFN_GetPrivateProfileSectionNamesA)lib.resolve("GetPrivateProfileSectionNamesA");
        fnGetPrivateProfileSectionA = (PFN_GetPrivateProfileSectionA)lib.resolve("GetPrivateProfileSectionA");
        fnGetPrivateProfileStringA = (PFN_GetPrivateProfileStringA)lib.resolve("GetPrivateProfileStringA");
        fnWritePrivateProfileStringA = (PFN_WritePrivateProfileStringA)lib.resolve("WritePrivateProfileStringA");
    }
}
QIniFile::~QIniFile()
{

}

void QIniFile::LoadFile(const char* sPath)
{
    m_sPath = sPath;
}

void  QIniFile::GetSectionNames(std::vector<std::string>& ar)
{
    const unsigned long LEN = GetSectionNames(NULL, 0);
    if (LEN == 0)
        return;

    char* psz = new char[LEN + 1];

    GetSectionNames(psz, LEN);
    ParseString(psz, ar);

    delete[] psz;
}

unsigned long QIniFile::GetSectionNames(char* lpBuffer, unsigned long dwBufSize)
{
    if (lpBuffer == NULL)
    {
        // just calculate the required buffer size
        unsigned long dwLen = DEF_PROFILE_THRESHOLD;
        char* psz = new char[dwLen + 1];
        unsigned long dwCopied = fnGetPrivateProfileSectionNamesA(psz, dwLen, m_sPath.c_str());
        while (dwCopied + 2 >= dwLen)
        {
            dwLen += DEF_PROFILE_THRESHOLD;
            delete[] psz;
            psz = new char[dwLen + 1];
            dwCopied = fnGetPrivateProfileSectionNamesA(psz, dwLen, m_sPath.c_str());
        }

        delete[] psz;
        return dwCopied + 2;
    }
    else
    {
        return fnGetPrivateProfileSectionNamesA(lpBuffer, dwBufSize, m_sPath.c_str());
    }
}

void QIniFile::GetKey_Value(const char* lpSection/*段名*/, std::vector<std::string>& ar)
{
    unsigned long Len = GetKey_Value(lpSection, NULL, 0);

    char* psz = new char[Len + 1];

    GetKey_Value(lpSection, psz, Len);
    ParseString(psz, ar);

    delete[] psz;
}

unsigned long QIniFile::GetKey_Value(const char* lpSection, char* lpBuffer, unsigned long dwBufSize)
{
    if (lpBuffer != NULL)
        *lpBuffer = '\0';

    if (lpSection == NULL)
        return 0;

    if (lpBuffer == NULL)
    {
        // just calculate the required buffer size
        unsigned long dwLen = DEF_PROFILE_THRESHOLD;
        char* psz = new char[dwLen + 1];
        unsigned long dwCopied = fnGetPrivateProfileSectionA(lpSection, psz, dwLen, m_sPath.c_str());

        while (dwCopied + 2 >= dwLen)
        {
            dwLen += DEF_PROFILE_THRESHOLD;
            delete[] psz;
            psz = new char[dwLen + 1];
            dwCopied = fnGetPrivateProfileSectionA(lpSection, psz, dwLen, m_sPath.c_str());
        }

        delete[] psz;
        return dwCopied + 2;
    }
    else
    {
        return fnGetPrivateProfileSectionA(lpSection, lpBuffer, dwBufSize, m_sPath.c_str());
    }
}


int QIniFile::ParseString(char* buff, std::vector<std::string>& ar)
{
    if (buff == NULL)
        return FALSE;

    char* p = buff;
    unsigned long dwLen = strlen(p);

    while (dwLen > 0)
    {
        ar.push_back(std::string(p));
        p = &p[dwLen + 1];
        dwLen = strlen(p);
    }
    return TRUE;
}

void QIniFile::GetKeyNames(const char* lpSection/*段名*/, std::vector<std::string>& ar)
{
    std::vector<std::string> key_value;
    GetKey_Value(lpSection, key_value);//先得到所有的key_value，然后解析出来

    int num = key_value.size();

    for (int i = 0; i < num; i++)
    {
        int pos = key_value[i].find('=', 0);
        if (-1 == pos)
            ar.push_back(key_value[i]);
        else
            ar.push_back(key_value[i].substr(0, pos));
    }
}

unsigned long QIniFile::GetValue(const char* lpSection/*段名*/, const char* sKey/*Key值*/, std::string& value)
{
    if (lpSection == NULL || sKey == NULL)
        return FALSE;

    char val[512] = { '\0' };

    unsigned long ret = fnGetPrivateProfileStringA(lpSection, sKey, "", val, 512, m_sPath.c_str());

    value = val;
    return ret;
}

unsigned long QIniFile::GetValue(const QString &section, const QString &key, QVariant &val)
{
    std::string sValue;
    int ret = GetValue(section.toUtf8().data(), key.toUtf8().data(), sValue);
    if (!ret)
        val = QVariant();
    else {
        val = QString::fromUtf8(sValue.c_str());
    }
    return ret;
}

int QIniFile::SetValue(const char* lpSection, const char* lpKey, const char* lpValue)
{
    if (lpSection == NULL || lpKey == NULL)
        return FALSE;

    return fnWritePrivateProfileStringA(lpSection, lpKey, lpValue == NULL ? "" : lpValue, m_sPath.c_str());
}

int QIniFile::SetValue(const QString &section, const QString &key, const QString &val)
{
    return SetValue(section.toUtf8().data(), key.toUtf8().data(), val.toUtf8().data());
}

int QIniFile::DeleteSection(const char* lpSection)
{
    return fnWritePrivateProfileStringA(lpSection, NULL, "", m_sPath.c_str());
}

int QIniFile::DeleteKey(const char* lpSection, const char* lpKey)
{
    return fnWritePrivateProfileStringA(lpSection, lpKey, NULL, m_sPath.c_str());
}

